package middleware

import (
	"bytes"
	"github.com/gin-gonic/gin"
	"github.com/sirupsen/logrus"
	"io"
	"net/http"
	"strings"
	"time"
)

type LogInfo struct {
	Ip           string `json:"ip"`           // 请求IP
	Method       string `json:"method"`       // 方法
	Url          string `json:"url"`          // url
	Params       string `json:"params"`       //参数
	ResponseCode int    `json:"responseCode"` //响应码
	ResponseBody string `json:"responseBody"` // 响应
	Duration     int64  `json:"duration"`     // 处理时间
}

func HttpLog() gin.HandlerFunc {
	return func(ctx *gin.Context) {
		startTime := time.Now().Unix()
		method := ctx.Request.Method
		urlList := strings.Split(ctx.Request.URL.String(), "?")
		ip := ctx.ClientIP()
		body, err := io.ReadAll(ctx.Request.Body)
		if err != nil {
			logrus.Error("中间件HttpLog记录到错误请求：", err)
		}
		// 等于拷贝一份往下传递,否则下接口的方法中拿不到请求体数据
		ctx.Request.Body = io.NopCloser(bytes.NewBuffer(body))
		params := ""
		switch method {
		case http.MethodGet:
			if len(urlList) > 1 {
				params = urlList[1]
			}
		case http.MethodPost:
			params = string(body)
		}
		blw := &ResponseWriterWrapper{Body: bytes.NewBufferString(""), ResponseWriter: ctx.Writer}
		ctx.Writer = blw
		ctx.Next()
		endTime := time.Now().Unix()
		info := LogInfo{
			Ip:           ip,
			Method:       method,
			Url:          urlList[0],
			Params:       params,
			ResponseCode: blw.Status(),
			ResponseBody: blw.Body.String(),
			Duration:     endTime - startTime,
		}
		if info.Duration > 2000 {
			logrus.Debug(info)
		}
	}
}

type ResponseWriterWrapper struct {
	gin.ResponseWriter
	Body *bytes.Buffer // 缓存
}

func (w ResponseWriterWrapper) Write(b []byte) (int, error) {
	w.Body.Write(b)
	return w.ResponseWriter.Write(b)
}

func (w ResponseWriterWrapper) WriteString(s string) (int, error) {
	w.Body.WriteString(s)
	return w.ResponseWriter.WriteString(s)
}
